package cn.xlunzi.games.view

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.os.Handler
import android.text.TextPaint
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.SurfaceHolder
import android.view.SurfaceView
import cn.xlunzi.games.R
import cn.xlunzi.games.common.Constant
import cn.xlunzi.games.utils.ColorUtil
import cn.xlunzi.games.utils.PrintUtil


/**
 * Created by SunLW on 2018-04-01.
 */
class LeiView(ctx: Context, attrs: AttributeSet?, defStyleRes: Int) : SurfaceView(ctx, attrs, defStyleRes), SurfaceHolder.Callback {

    constructor(ctx: Context) : this(ctx, null)
    constructor(ctx: Context, attrs: AttributeSet?) : this(ctx, attrs, 0)

    // SurfaceHolder
    private lateinit var mHolder: SurfaceHolder
    // 用于绘图的Canvas

    /** 每30帧刷新一次屏幕 */
    private val TIME_IN_FRAME = 50L

    private lateinit var mPath: Path
    private lateinit var mPaint: Paint
    private lateinit var textPaint: Paint

    private val baseDp100 = resources.getDimension(R.dimen.px300)
    private val padding = baseDp100 / 50

    private val leiWidth = baseDp100 / 2

    /** x轴偏移量 */
    private var offsetX = 0.0f
    /** y轴偏移量 */
    private var offsetY = 0.0f

    private var singlePointer = false
    private val mGestureDetector = GestureDetector(ctx, GestureListener(this))

    private lateinit var numList: List<Int>
    private lateinit var typeList: List<Int>

    private var leiColumn: Int = 0
    private var leiRow: Int = 0

    private var startTime: Long = 0

    private var listener: OnListener? = null

    fun addListener(listener: OnListener) {
        this.listener = listener
    }

    init {
        initView()
    }

    private fun initView() {
        mHolder = holder //获取SurfaceHolder对象
        mHolder.addCallback(this) //注册SurfaceHolder的回调方法
        isFocusable = true
        isFocusableInTouchMode = true
        this.keepScreenOn = true

        mPath = Path()

        mPaint = Paint()
        mPaint.isAntiAlias = true
        mPaint.style = Paint.Style.STROKE
        mPaint.strokeWidth = 1.0f

        textPaint = TextPaint()
        textPaint.isAntiAlias = true
//        textPaint.style = Paint.Style.FILL
//        textPaint.strokeWidth = 1.0f
        textPaint.textSize = baseDp100 / 3
        textPaint.textAlign = Paint.Align.CENTER

        setBackgroundColor(Color.WHITE)
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if (canvas == null) {
            return
        }
        drawLayer(canvas)
    }

    // 绘图操作
    private fun drawLayer() {
        try {
            // 拿到当前画布 然后锁定
            val mCanvas: Canvas = mHolder.lockCanvas()
            drawLayer(mCanvas)
            // 绘制结束后解锁显示在屏幕上
            mHolder.unlockCanvasAndPost(mCanvas)
        } catch (e: Exception) {
            PrintUtil.err(e.message)
        }
    }

    private fun drawLayer(canvas: Canvas) {
        canvas.translate(offsetX, offsetY)

        mPath.reset()

        mPaint.style = Paint.Style.FILL
        mPaint.color = Color.parseColor(ColorUtil.BLUE)

        val startCol: Int = ((0 - offsetX - baseDp100 / 10) / (padding + leiWidth)).toInt()
        val startRow: Int = ((0 - offsetY - baseDp100 / 10) / (padding + leiWidth)).toInt()

        val endCol: Int = ((width - offsetX - baseDp100 / 10) / (padding + leiWidth)).toInt() + 1
        val endRow: Int = ((height - offsetY - baseDp100 / 10) / (padding + leiWidth)).toInt() + 1

        // TODO 循环
        numList.forEachIndexed { index, num ->
            // 行
            val row = index / leiColumn // [0,COLUMN]
            // 列
            val col = index % leiColumn// [0,COLUMN]

            if (col < startCol || col > endCol || row < startRow || row > endRow) {
                return@forEachIndexed
            }

            // 显示
            when (typeList[index]) {
                Constant.TYPE_HIDE -> {
                    mPaint.color = Color.parseColor(ColorUtil.BLUE)
                    canvas.drawPath(getItem(col, row, mPath), mPaint)
                }
                Constant.TYPE_SIGN -> {
                    mPaint.color = Color.parseColor(ColorUtil.RED)
                    canvas.drawPath(getItem(col, row, mPath), mPaint)

                    val floatX = baseDp100 / 10 + (padding + leiWidth) * col
                    val floatY = baseDp100 / 10 + (padding + leiWidth) * row
                    textPaint.color = Color.parseColor(ColorUtil.WHITE)
                    canvas.drawText("雷", floatX + leiWidth / 2, floatY + leiWidth / 2 + textPaint.textSize / 2, textPaint)
                }
                Constant.TYPE_SHOW -> {
                    mPaint.color = Color.LTGRAY
                    canvas.drawPath(getItem(col, row, mPath), mPaint)

                    // 显示
                    val text: String = when {
                        numList[index] == 0 -> ""
                        else -> num.toString()
                    }
                    val floatX = baseDp100 / 10 + (padding + leiWidth) * col
                    val floatY = baseDp100 / 10 + (padding + leiWidth) * row
                    textPaint.color = Color.parseColor(ColorUtil.BLUE)
                    canvas.drawText(text, floatX + leiWidth / 2, floatY + leiWidth / 2 + textPaint.textSize / 2, textPaint)
                }
            }
        }
    }

    private fun getItem(col: Int, row: Int, path: Path): Path {
        path.reset()

        val floatX = baseDp100 / 10 + (padding + leiWidth) * col
        val floatY = baseDp100 / 10 + (padding + leiWidth) * row

        path.moveTo(floatX, floatY)
        path.lineTo(floatX + leiWidth, floatY)
        path.lineTo(floatX + leiWidth, floatY + leiWidth)
        path.lineTo(floatX, floatY + leiWidth)
        path.lineTo(floatX, floatY)

        return path
    }

    fun initLei(numList: List<Int>, typeList: List<Int>, column: Int, row: Int) {
        this.numList = numList
        this.typeList = typeList

        this.leiColumn = column
        this.leiRow = row

        invalidate()
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (event.action == MotionEvent.ACTION_DOWN) {
            singlePointer = true
        }
        if (event.pointerCount == 1 && singlePointer) {
            mGestureDetector.onTouchEvent(event)
        } else if (event.pointerCount == 2) { // "多点触控"
            singlePointer = false
        }
        return true
    }

    private val threadHandler = Handler()

    private fun startOnLoopDraw() {
        threadHandler.postDelayed(object : Runnable {
            override fun run() {
                drawLayer()
                threadHandler.postDelayed(this, TIME_IN_FRAME)
            }
        }, TIME_IN_FRAME)
    }

    private fun stopOnLoopDraw() {
        threadHandler.removeCallbacksAndMessages(null)
    }

    override fun surfaceCreated(holder: SurfaceHolder?) {
//        startOnLoopDraw()
    }

    override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
    }

    override fun surfaceDestroyed(holder: SurfaceHolder?) {
//        stopOnLoopDraw()
    }

    inner class GestureListener(private val leiView: LeiView) : GestureDetector.SimpleOnGestureListener() {

        override fun onDown(event: MotionEvent): Boolean {
            return false
        }

        override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
            return false
        }

        override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
            val k = Math.round(distanceX)
            offsetX -= k
            // 上负下正- 往下滑则减
            val j = Math.round(distanceY)
            offsetY -= j

            if (offsetX > 0) { // 限制左边界被拉出
                offsetX = 0f
            } else {
                val colOffset = (padding + leiWidth) * leiColumn * (-1) + width - baseDp100 / 5 + padding
                if (offsetX < colOffset) { // 限制右边界被拉出
                    offsetX = colOffset
                }
            }
            if (offsetY > 0) { // 限制上边界被拉出
                offsetY = 0f
            } else { // 限制下边界被拉出
                val rowOffset = (padding + leiWidth) * leiRow * (-1) + height - baseDp100 / 5 + padding
                if (offsetY < rowOffset) { // 限制右边界被拉出
                    offsetY = rowOffset
                }
            }

            val diffTime = System.currentTimeMillis() - startTime
            if (diffTime > 50) {
                leiView.invalidate()
                startTime = System.currentTimeMillis()
            }
            return false
        }

        override fun onShowPress(event: MotionEvent) {
        }

        override fun onLongPress(event: MotionEvent) {
            val col: Int = ((event.x - offsetX - baseDp100 / 10) / (padding + leiWidth)).toInt()
            val row: Int = ((event.y - offsetY - baseDp100 / 10) / (padding + leiWidth)).toInt()

            if (listener != null) {
                listener!!.onItemLongClick(row * leiColumn + col)
            }
        }

        override fun onSingleTapUp(event: MotionEvent): Boolean {
            return false
        }

        override fun onSingleTapConfirmed(event: MotionEvent): Boolean {
            val col: Int = ((event.x - offsetX - baseDp100 / 10) / (padding + leiWidth)).toInt()
            val row: Int = ((event.y - offsetY - baseDp100 / 10) / (padding + leiWidth)).toInt()

            if (listener != null) {
                listener!!.onItemClick(row * leiColumn + col)
                return true
            }
            return false
        }
    }

    interface OnListener {
        fun onItemClick(position: Int)

        fun onItemLongClick(position: Int)
    }
}